package com.njtoyo.taxi.admin.aop;

import com.njtoyo.taxi.admin.rest.wrapper.Identity;
import com.taxi.entity.common.RestResult;
import com.taxi.entity.common.ResultEnum;
import com.njtoyo.taxi.entity.backend.AdminUser;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@RestControllerAdvice
@Slf4j
@SuppressWarnings("unchecked")
public class MvcControllerAdvice {

    @ModelAttribute("identity")
    public Identity getIdentityFromToken(HttpServletRequest request) {
        return this.getIdentityFromTokenRequest(request);
    }

    @ModelAttribute("admin")
    public AdminUser getAdminFromToken(HttpServletRequest request) {
        Identity identity = this.getIdentityFromTokenRequest(request);
        return Objects.isNull(identity) ? null : identity.getAdminUser();
    }

    private Identity getIdentityFromTokenRequest(HttpServletRequest request){
        return (Identity) request.getAttribute("identity");
    }

    @ExceptionHandler(YDException.class)
    public RestResult handleYDException(YDException e) {
        log.error("YDException error : {}", e.getMessage());
        e.printStackTrace();
        return RestResult.failed(e.getMessage());
    }

    @ExceptionHandler(value = Exception.class)
    public RestResult errorHandler(Exception e) {
        log.error("error : {}", e.getMessage());
        e.printStackTrace();
        return RestResult.fail();
    }



    @ExceptionHandler
    public RestResult handle(MethodArgumentNotValidException error) {

        RestResult restResult = new RestResult(ResultEnum.PARAMS_ERROR);

        List<FieldError> errors = error.getBindingResult().getFieldErrors();

        Map errorMap = new HashMap();

        for (FieldError fieldError : errors) {
            errorMap.put(fieldError.getField(), fieldError.getDefaultMessage());
        }

        String msg = Objects.isNull(errorMap.values().stream().collect(Collectors.joining(","))) ? restResult.getMsg() : errorMap.values().stream().collect(Collectors.joining(",")).toString();
        restResult.setMsg(msg);

        return restResult;
    }

    @ExceptionHandler
    public RestResult handle(BindException error) {

        RestResult restResult = new RestResult(ResultEnum.PARAMS_ERROR);

        List<FieldError> errors = error.getBindingResult().getFieldErrors();

        Map errorMap = new HashMap();

        for (FieldError fieldError : errors) {
            errorMap.put(fieldError.getField(), fieldError.getDefaultMessage());
        }

        String msg = Objects.isNull(errorMap.values().stream().collect(Collectors.joining(","))) ? restResult.getMsg() : errorMap.values().stream().collect(Collectors.joining(",")).toString();
        restResult.setMsg(msg);

        return restResult;
    }

}
